﻿<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>jQXB unit tests</title>
    <script src="Scripts/jQXB.1.2.js" type="text/javascript"></script>
    <script src="Scripts/jquery-1.6.2.min.js" type="text/javascript"></script>
    <script src="Scripts/qunit.js" type="text/javascript"></script>
    <link href="Scripts/qunit.css" rel="stylesheet" type="text/css" />
    <script type="text/javascript">
        var header = "<h2>jQXB Unit Test</h2>";
        var Person1 = {
            'Name': 'Anthony',
            'Surname': 'Murray',
            'Address': { 'Street': 'Carnaby Street', 'ZipCode': 'YTSCH', 'Phones': [{ 'prefix': '010', 'number': 23094895 }, { 'prefix': '0185', 'number': 2930940 }, { 'prefix': '03485', 'number': 3234567 }] },
            'MonthlyAmount': [13498, 23456, 12345, 12345, 38728, 0, 34231, 39748.95, 34534, 2134, 567, 666, 345]
        };

        var Person2 = {
            'Name': 'John',
            'Surname': 'Blake',
            'Address': { 'Street': 'Abbey Road', 'ZipCode': 'ABCDE', 'Phones': [{ 'prefix': '097', 'number': 23034523 }, { 'prefix': '052', 'number': 29302345 }] },
            'MonthlyAmount': [3456, 2134.5, 0, 345, 678, 1234, 354235, 32345.95, 257, 4564, 3562, 2346, 34555]
        };
        var Person3 = {
            'Name': 'Andrew',
            'Surname': 'McDowell',
            'Address': { 'Street': 'Wall Street', 'ZipCode': 'XYZ123', 'Phones': [{ 'prefix': '0342', 'number': 1234567 }, { 'prefix': '0456', 'number': 21341234 }, { 'prefix': '050', 'number': 37802345 }] },
            'MonthlyAmount': [345, 457734.54, 40, 4345, 45643, 34565, 97685, 95685.95, 467856, 5674, 56785, 346, 344565]
        };

        var Person4 = {
            'Name': 'Test',
            'Surname': 'Person',
            'Address': { 'Street': 'Wall Street1', 'ZipCode': 'ABZ123', 'Phones': [{ 'prefix': '0342', 'number': 1234567 }, { 'prefix': '0456', 'number': 21341234 }] },
            'MonthlyAmount': [345, 457734.54, 40, 4345, 45643, 34565, 97685, 95685.95, 467856, 5674, 56785, 346, 344565]
        };
        $(function () {

            module("Initialization");
            test("initialize jQXB", 1, function () {
                jQXB.initialize();
                ok(jQXB.initialized == true, "Initialization status was correctly set");
            });

            module("binding syntax");
            test("binding std syntax", 10, function () {

                jQXB.initialize();
                jQXB.setDataSource("MyDataSource", Person1);
                jQXB.doBind("MyDataSource");
                ok(jQuery('#inputElement').val() == "Anthony", "Bind to texbox");
                ok(jQuery('#spanElement').html() == "Anthony", "Bind to span html");
                ok(jQuery('#hrefElement').attr('href') == "Anthony", "Bind to href");
                ok(jQuery('#divElement').text() == "Anthony", "Bind to div text");
                ok(jQuery("#checkBoxElement").val() == "Anthony", "Bind to checkbox value");
                jQXB.setDataSource("MyDataSource", Person2);
                jQXB.doBind("MyDataSource");
                ok(jQuery('#inputElement').val() == "John", "Bind to texbox");
                ok(jQuery('#spanElement').html() == "John", "Bind to span html");
                ok(jQuery('#hrefElement').attr('href') == "John", "Bind to href");
                ok(jQuery('#divElement').text() == "John", "Bind to div text");
                ok(jQuery("#checkBoxElement").val() == "John", "Bind to checkbox value");

            });

            test("binding fluent syntax", 10, function () {
                jQXB.initialize();
                jQXB.setDataSource("MyDataSource", Person1).doBind("MyDataSource");
                ok(jQuery('#inputElement').val() == "Anthony", "Bind to texbox");
                ok(jQuery('#spanElement').html() == "Anthony", "Bind to span html");
                ok(jQuery('#hrefElement').attr('href') == "Anthony", "Bind to href");
                ok(jQuery('#divElement').text() == "Anthony", "Bind to div text");
                ok(jQuery("#checkBoxElement").val() == "Anthony", "Bind to checkbox value");
                jQXB.setDataSource("MyDataSource", Person2).doBind("MyDataSource");
                ok(jQuery('#inputElement').val() == "John", "Bind to texbox");
                ok(jQuery('#spanElement').html() == "John", "Bind to span html");
                ok(jQuery('#hrefElement').attr('href') == "John", "Bind to href");
                ok(jQuery('#divElement').text() == "John", "Bind to div text");
                ok(jQuery("#checkBoxElement").val() == "John", "Bind to checkbox value");
            });




            module("simple binding");
            test("bind and modify", 3, function () {
                jQXB.initialize();
                jQXB.setDataSource("MyDataSource", Person2).doBind();
                ok(jQXB.getDataSource("MyDataSource").Name == "John", "Data source correctly setted");
                ok(jQuery('#inputElement').val() == "John", "Html Element correctly setted");
                jQuery('#inputElement').val('Sean');
                jQuery('#inputElement').change();
                jQXB.refreshControls("MyDataSource");
                ok(jQXB.getDataSource("MyDataSource").Name == 'Sean', "Data source changed after value changed");

                //return Person2.Name back to initial value
                Person2.Name = "John";
            });

            test("binding with list box for particular data source only", 8, function () {
                jQXB.initialize();
                jQXB.setDataSource("MyDataSource", Person1); // this data source  will not be bound
                jQXB.setDataSource("ListSource", Person1.Address.Phones).doBind("ListSource");
                var count = Person1.Address.Phones.length;
                ok($("#listBox > option").length == count, "ListBox contains " + count + " elements as expected");
                //check each #listBox item for correct bound values and texts
                for (var i = 0; i < count; i++) {
                    ok($("#listBox > option").eq(i).val() == Person1.Address.Phones[i].prefix, "ListBox " + i + " value was correctly set");
                    ok($("#listBox > option").eq(i).text() == Person1.Address.Phones[i].number, "ListBox " + i + " text was correctly set");
                }
                // These elements were not bound with MyDataSource : 
                ok(jQuery('#inputElement').val() != Person1.Name
                     && jQuery('#spanElement').html() != Person1.Name
                     && jQuery('#hrefElement').attr('href') != Person1.Name
                     && jQuery('#divElement').text() != Person1.Name, "");
            });

            test("binding with list box using datapath", 8, function () {
                jQXB.initialize();
                jQXB.setDataSource("MyDataSourcePath", Person1).doBind("MyDataSourcePath"); // this data source  will not be bound
                var count = Person1.Address.Phones.length;
                ok($("#listBoxDataPath > option").length == count, "ListBox contains " + count + " elements as expected");
                //check each #listBox item for correct bound values and texts
                for (var i = 0; i < count; i++) {
                    ok($("#listBoxDataPath > option").eq(i).val() == Person1.Address.Phones[i].prefix, "ListBox " + i + " value was correctly set");
                    ok($("#listBoxDataPath > option").eq(i).text() == Person1.Address.Phones[i].number, "ListBox " + i + " text was correctly set");
                }
                // These elements were not bound with MyDataSource : 
                ok(jQuery('#inputElement').val() != Person1.Name
                     && jQuery('#spanElement').html() != Person1.Name
                     && jQuery('#hrefElement').attr('href') != Person1.Name
                     && jQuery('#divElement').text() != Person1.Name, "");
            });

            test("Template binding", 1, function () {
                jQXB.initialize();
                jQXB.setDataSource("MyDataSource", Person1.Address.Phones).doBind("MyDataSource");
                ok($("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemdatasourceidx=0] [jqxb-itemdatamember=prefix]").val() == "010"
                    && $("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemdatasourceidx=0] [jqxb-itemdatamember=number]").val() == 23094895
                    && $("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemdatasourceidx=1] [jqxb-itemdatamember=prefix]").val() == "0185"
                    && $("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemdatasourceidx=1] [jqxb-itemdatamember=number]").val() == 2930940
                   && $("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemdatasourceidx=2] [jqxb-itemdatamember=prefix]").val() == "03485"
                    && $("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemdatasourceidx=2] [jqxb-itemdatamember=number]").val() == 3234567
                 , "Data source was correctly bound with template ");

            });

            test("Template binding datapath", 1, function () {
                jQXB.initialize();
                jQXB.setDataSource("MyDataSourcePath", Person1).doBind("MyDataSourcePath");
                ok($("[jqxb-templatecontainer=phoneTemplateDataPath] [jqxb-itemdatasourceidx=0] [jqxb-itemdatamember=prefix]").val() == "010"
                    && $("[jqxb-templatecontainer=phoneTemplateDataPath] [jqxb-itemdatasourceidx=0] [jqxb-itemdatamember=number]").val() == 23094895
                    && $("[jqxb-templatecontainer=phoneTemplateDataPath] [jqxb-itemdatasourceidx=1] [jqxb-itemdatamember=prefix]").val() == "0185"
                    && $("[jqxb-templatecontainer=phoneTemplateDataPath] [jqxb-itemdatasourceidx=1] [jqxb-itemdatamember=number]").val() == 2930940
                   && $("[jqxb-templatecontainer=phoneTemplateDataPath] [jqxb-itemdatasourceidx=2] [jqxb-itemdatamember=prefix]").val() == "03485"
                    && $("[jqxb-templatecontainer=phoneTemplateDataPath] [jqxb-itemdatasourceidx=2] [jqxb-itemdatamember=number]").val() == 3234567
                 , "Data source was correctly bound with template ");

            });

            module("Data source operations and binding");
            test("adding 2 data sources", 1, function () {
                jQXB.initialize();
                jQXB.setDataSource("MyDataSource", Person1);
                jQXB.setDataSource("NewDataSource", Person2);
                ok(jQXB.getDataSource("MyDataSource") != undefined && jQXB.getDataSource("NewDataSource") != undefined, "2 data sources were succsessfully created");
            });

            test("All data sources are bound when invoke doBind without parameters ", 10, function () {
                jQXB.initialize();
                jQXB.setDataSource("MyDataSource", Person4);
                jQXB.setDataSource("ListSource", Person4.Address.Phones);
                // No binding before bind : 
                ok(jQuery('#inputElement').val() != Person4.Name
                     && jQuery('#spanElement').html() != Person4.Name
                     && jQuery('#hrefElement').attr('href') != Person4.Name
                     && jQuery('#divElement').text() != Person4.Name, "");
                var count = Person4.Address.Phones.length;
                for (var i = 0; i < count; i++) {
                    ok($("#listBox > option").eq(i).val() != Person4.Address.Phones[i].prefix, "");
                    ok($("#listBox > option").eq(i).text() != Person4.Address.Phones[i].number, "");
                }
                jQXB.doBind();
                // All data sources are bound after doBind() 
                ok(jQuery('#inputElement').val() == Person4.Name
                     && jQuery('#spanElement').html() == Person4.Name
                     && jQuery('#hrefElement').attr('href') == Person4.Name
                     && jQuery('#divElement').text() == Person4.Name, "");
                for (var i = 0; i < count; i++) {
                    ok($("#listBox > option").eq(i).val() == Person4.Address.Phones[i].prefix, "");
                    ok($("#listBox > option").eq(i).text() == Person4.Address.Phones[i].number, "");
                }
            });

            test("Set up data source with object's array and check retrieving from data source", 4, function () {
                jQXB.initialize();
                var objects = [Person1, Person2, Person3, Person4];
                jQXB.setDataSource("MyDataSource", objects);
                var count = jQXB.getDataSource("MyDataSource").length;
                for (var i = 0; i < count; i++) {
                    ok(jQXB.getDataSource("MyDataSource")[i] === objects[i], "Object " + i + " was correctly retrieved from data source");
                }
            });

            test("get original  value from data source", 1, function () {
                jQXB.initialize();
                jQXB.setDataSource("MyDataSource", Person1);
                var bAreEqual = true;
                var PersonCloned = jQXB.getDataSourceOrigValue("MyDataSource");
                for (var prop in Person1) {
                    if (Person1.hasOwnProperty(prop)) {
                        if (Person1[prop] != PersonCloned[prop])
                            bAreEqual = false;
                    }
                }
                ok(bAreEqual, "Object was correctly retrieved from data source");
            });

            test("add/delete  objects to/from data source", 5, function () {
                jQXB.initialize();
                jQXB.setDataSource("MyDataSource", [Person1]);
                ok(jQXB.getDataSource("MyDataSource").length == 1, "array with 1 object is currently in the  data source");
                jQXB.addObjectToDataSource("MyDataSource", Person2);
                ok(jQXB.getDataSource("MyDataSource").length == 2, "array with 2 objects is currently in the  data source");
                jQXB.addObjectToDataSource("MyDataSource", Person3);
                ok(jQXB.getDataSource("MyDataSource").length == 3, "array with 3 objects is currently in the  data source");
                jQXB.deleteObjectFromDataSource("MyDataSource", 1);
                ok(jQXB.getDataSource("MyDataSource").length == 2 && jQXB.getDataSource("MyDataSource")[0] === Person1
            && jQXB.getDataSource("MyDataSource")[1] === Person3, "array with 2 objects is currently in the  data source");
                jQXB.deleteObjectFromDataSource("MyDataSource", 0);
                ok(jQXB.getDataSource("MyDataSource").length == 1 && jQXB.getDataSource("MyDataSource")[0] === Person3, "1 object is currently in the  data source");
            });

            test("Set data source with and without  autorefresh", 10, function () {
                jQXB.initialize();
                //set data source without possibility to autorefesh
                jQXB.setDataSource("MyDataSource", Person1).doBind("MyDataSource"); // Person1.Name=='Anthony'
                ok($("#inputElement").val() == 'Anthony' &&
                jQuery('#spanElement').html() == 'Anthony' &&
                jQuery('#hrefElement').attr('href') == 'Anthony' &&
                jQuery('#divElement').text() == 'Anthony', "Initial set up  ");
                // change  #inputElement value and look what  will happen with another bound elements
                $("#inputElement").val("Kevin");
                $("#inputElement").change();
                // autorefresh will not happen
                ok(jQuery('#spanElement').html() == 'Anthony', "Control was not refreshed");
                ok(jQuery('#hrefElement').attr('href') == 'Anthony', "Control was not refreshed");
                ok(jQuery('#divElement').text() == 'Anthony', "Control was not refreshed");
                //set data source without possibility to autorefesh:
                jQXB.setDataSource("MyDataSource", Person1, false).doBind("MyDataSource"); //Person1.Name == 'Kevin'
                // change  #inputElement value and look what  will happen with another bound elements
                $("#inputElement").val("Bill");
                $("#inputElement").change();
                // autorefresh will not happen
                ok(jQuery('#spanElement').html() == 'Kevin', "Control was not refreshed");
                ok(jQuery('#hrefElement').attr('href') == 'Kevin', "Control was not refreshed");
                ok(jQuery('#divElement').text() == 'Kevin', "Control was not refreshed");
                //set data source with  ability to autorefesh
                jQXB.setDataSource("MyDataSource", Person1, true); //Person1.Name == 'Bill'
                // change  #inputElement value and look what  will happen with another bound elements
                $("#inputElement").val("Anthony"); // return Person1.Name back to 'Anthony'
                $("#inputElement").change();
                // now autorefresh should happen
                ok(jQuery('#spanElement').html() == "Anthony", "Now control was  refreshed");
                ok(jQuery('#hrefElement').attr('href') == "Anthony", "Now control was  refreshed");
                ok(jQuery('#divElement').text() == "Anthony", "Now control was  refreshed");
            });

            module("Template operations");
            test("clearTemplateInstances", 2, function () {
                jQXB.initialize();
                jQXB.setDataSource('MyDataSource', Person1.Address.Phones).doBind('MyDataSource');
                ok($("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemtemplate]").length == 3, "There are 3 template rows on the page now");
                jQXB.clearTemplateInstances("phoneTemplate");
                ok($("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemtemplate]").length == 0, "All template  rows have been deleted from the  page ");
            });

            test("deleteTemplateRow", 4, function () {
                jQXB.initialize();
                jQXB.setDataSource('MyDataSource', Person1.Address.Phones).doBind('MyDataSource');
                ok($("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemtemplate]").length == 3, "There are 3 template rows on the page now");
                ok($("[jqxb-templatecontainer=phoneTemplate] [id]").eq(0).attr("id") == "phonerow_0"
                    && $("[jqxb-templatecontainer=phoneTemplate] [id]").eq(1).attr("id") == "phonerow_1"
                     && $("[jqxb-templatecontainer=phoneTemplate] [id]").eq(2).attr("id") == "phonerow_2"
                    && $("[jqxb-templatecontainer=phoneTemplate] [id]").eq(0).attr("jqxb-itemdatasourceidx") == 0
                    && $("[jqxb-templatecontainer=phoneTemplate] [id]").eq(1).attr("jqxb-itemdatasourceidx") == 1
                     && $("[jqxb-templatecontainer=phoneTemplate] [id]").eq(2).attr("jqxb-itemdatasourceidx") == 2
                 , " Template rows have correct IDs and datasource indexes ");
                jQXB.deleteTemplateRow('phoneTemplate', 1);
                ok($("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemtemplate]").length == 2, "There are 2 template rows on the page now after removing ");
                ok($("[jqxb-templatecontainer=phoneTemplate] [id]").eq(0).attr("id") == "phonerow_0"
                    && $("[jqxb-templatecontainer=phoneTemplate] [id]").eq(1).attr("id") == "phonerow_1"
                     && $("[jqxb-templatecontainer=phoneTemplate] [id]").eq(0).attr("jqxb-itemdatasourceidx") == 0
                    && $("[jqxb-templatecontainer=phoneTemplate] [id]").eq(1).attr("jqxb-itemdatasourceidx") == 1
                     , " Template rows and datasource indexes were correctly renumbered ");
            });

            module("Events subscription and handlers");
            test("BeforeDataSourceBind/AfterDataSourceBind  events", 8, function () {
                var OnBeforeDataSourceBindCounter = 0;
                var OnAfterDataSourceBindCounter = 0;
                jQXB.initialize();
                function BeforeDataSourceBindhnd(dataSourceName, jsObject) {
                    switch (dataSourceName) {
                        case 'MyDataSource':
                            ok($("#inputElement").val() != "Luke", "OnBeforeDataSourceBind event has not completed yet");
                            ok(jQXB.getDataSource("MyDataSource").Name == "Anthony", "OnBeforeDataSourceBind event has not completed yet");
                            jsObject.Name = 'Luke'; // 
                            OnBeforeDataSourceBindCounter++;
                            break;
                    }
                }
                jQXB.addOnBeforeDataSourceBindhnd(BeforeDataSourceBindhnd);
                function AfterDataSourceBindhnd(dataSourceName, jsObject) {
                    switch (dataSourceName) {
                        case 'MyDataSource':
                            ok(jQXB.getDataSource("MyDataSource").Name == "Luke", "OnBeforeDataSourceBind event has already occured");
                            jsObject.Name = 'Anthony'; // Return test person Name to its original value
                            ok($("#inputElement").val() == "Luke", "OnBeforeDataSourceBind event has already occured ");
                            $("#inputElement").attr("value", "Jack");
                            OnAfterDataSourceBindCounter++;
                            break;
                    }
                }
                jQXB.addOnAfterDataSourceBindhnd(AfterDataSourceBindhnd);
                jQXB.setDataSource("MyDataSource", Person1);
                jQXB.doBind("MyDataSource");
                ok(jQXB.getDataSource("MyDataSource").Name == "Anthony", "OnAfterDataSourceBind event has already occured and object's Name was returned to its original value");
                ok($("#inputElement").val() == "Jack", "OnAfterDataSourceBind event has already occured ");
                ok(OnAfterDataSourceBindCounter == 1, "OnAfterDataSourceBind event  occured only 1 time");
                ok(OnBeforeDataSourceBindCounter == 1, "OnBeforeDataSourceBind event  occured only 1 time");
                //Clear event handlers for next tests:
                jQXB.delOnAfterDataSourceBindhnd(AfterDataSourceBindhnd);
                jQXB.delOnBeforeDataSourceBindhnd(BeforeDataSourceBindhnd);
            });

            test("BeforeUpdate / AfterUpdate  events", 13, function () {
                var OnBeforeUpdateCounter = 0;
                var OnAfterUpdateCounter = 0;
                var newValue = "Michael";
                jQXB.initialize();
                jQXB.setDataSource("MyDataSource", Person1);
                function BeforeUpdatehnd(dataSourceName, occurency, member, membername, value) {
                    switch (dataSourceName) {
                        case 'MyDataSource':
                            ok(occurency === null, "Occurency is null for objects");
                            ok(member == Person1.Name, " member is the object’s member containing the current value to be changed");
                            ok(membername == "Name", "membername is the name of object's property declared in jqxb-datamember attribute");
                            ok(value == newValue, "The new value was passed to the handler");
                            OnBeforeUpdateCounter++;
                            break;
                    }
                    return false;
                }
                jQXB.addOnBeforeUpdatehnd(BeforeUpdatehnd);
                function AfterUpdatehnd(dataSourceName, occurency, member, membername, value) {
                    switch (dataSourceName) {
                        case 'MyDataSource':
                            ok(occurency === null, "Occurency is null for objects");
                            ok(member === Person1.Name, " member is the object’s member containing the value just changed");
                            ok(membername == "Name", "membername is the name of object's property declared in jqxb-datamember attribute");
                            ok(value == newValue, "The new value was passed to the handler");
                            OnAfterUpdateCounter++;
                            break;
                    }
                }
                jQXB.addOnAfterUpdatehnd(AfterUpdatehnd);
                // Fire change event for #inputElement 
                $("#inputElement").val(newValue);
                ok(OnBeforeUpdateCounter == 0, " BeforeUpdate event has not occured yet");
                $("#inputElement").change();
                ok(OnBeforeUpdateCounter == 1, " BeforeUpdate event has already occured ");
                ok(OnAfterUpdateCounter == 1, " AfterUpdate event has already occured ");
                ok(jQXB.getDataSource("MyDataSource").Name == newValue, "  Data source was updated - the case when BeforeUpdate handler returns false");
                ok($("#inputElement").val() == newValue, " Binded textbox was   updated");
                //Clear event handlers for next tests 
                jQXB.delOnBeforeUpdatehnd(BeforeUpdatehnd);
                jQXB.delOnAfterUpdatehnd(AfterUpdatehnd);
                // Return Person.Name back to initial value for next tests:
                Person1.Name = 'Anthony';
            });

            test("BeforeUpdate  handler can return TRUE to cancel update", 8, function () {
                var OnBeforeUpdateCounter = 0;
                var OnAfterUpdateCounter = 0;
                var newValue = "Michael";
                jQXB.initialize();
                jQXB.setDataSource("MyDataSource", Person3);
                jQXB.addOnBeforeUpdatehnd(function (dataSourceName, occurency, member, membername, value) {
                    switch (dataSourceName) {
                        case 'MyDataSource':
                            ok(occurency === null, "Occurency is null for objects");
                            ok(member == Person3.Name, " member is the object’s member containing the current value to be changed");
                            ok(membername == "Name", "membername is the name of object's property declared in jqxb-datamember attribute");
                            ok(value == newValue, "The new value was passed to the handler");
                            OnBeforeUpdateCounter++;
                            break;
                    }
                    return true;
                });

                //                 Fire change event for #inputElement 
                $("#inputElement").val(newValue);
                $("#inputElement").change();
                ok(OnBeforeUpdateCounter == 1, " BeforeUpdate event has already occured ");
                ok(Person3.Name == 'Andrew', " Object's property update was CANCELED");
                ok(jQXB.getDataSource("MyDataSource").Name == 'Andrew', "  Data source object's property  update was CANCELED");
                ok($("#inputElement").val() == 'Andrew', " Binded textbox's  update was CANCELED too");
                //Clear event handlers for next tests 
                jQXB.delOnBeforeUpdatehnd(function (dataSourceName, occurency, member, membername, value) {
                    switch (dataSourceName) {
                        case 'MyDataSource':
                            ok(occurency === null, "Occurency is null for objects");
                            ok(member == Person3.Name, " member is the object’s member containing the current value to be changed");
                            ok(membername == "Name", "membername is the name of object's property declared in jqxb-datamember attribute");
                            ok(value == newValue, "The new value was passed to the handler");
                            OnBeforeUpdateCounter++;
                            break;
                    }
                    return true;
                });
            });

            test("BeforeUpdate / AfterUpdate  events for arrays", 12, function () {
                var OnBeforeUpdateCounter = 0;
                var OnAfterUpdateCounter = 0;
                var index = 1; // index of the element which is going to be changed
                var newValue = 555555;
                jQXB.initialize();
                jQXB.setDataSource("MyDataSource", Person1.Address.Phones).doBind("MyDataSource");
                function BeforeUpdatehnd(dataSourceName, occurency, member, membername, value) {
                    switch (dataSourceName) {
                        case 'MyDataSource':
                            ok(occurency == index, "element with " + index + " index in Phones array will be  changed ");
                            ok(member == Person1.Address.Phones[index].number, " member is the object’s member containing the current value to be changed");
                            ok(membername == "number", "membername is the name of object's property declared in jqxb-datamember attribute");
                            ok(value == newValue, "The new value was passed to the handler");
                            OnBeforeUpdateCounter++;
                            break;
                    }
                }
                jQXB.addOnBeforeUpdatehnd(BeforeUpdatehnd);
                function AfterUpdatehnd(dataSourceName, occurency, member, membername, value) {
                    switch (dataSourceName) {
                        case 'MyDataSource':
                            ok(occurency == index, "element with " + index + " index in Phones array was changed");
                            ok(member == Person1.Address.Phones[index].number, " member is the object’s member containing the value just changed");
                            ok(membername == "number", "membername is the name of object's property declared in jqxb-datamember attribute");
                            ok(value == newValue, "The new value was passed to the handler");
                            OnAfterUpdateCounter++;
                            break;
                    }
                }
                jQXB.addOnAfterUpdatehnd(AfterUpdatehnd);
                //Raise change event 
                $("[jqxb-templatecontainer=phoneTemplate]> [id=phonerow_" + index + "] [jqxb-itemdatamember=number]").val(newValue);
                $("[jqxb-templatecontainer=phoneTemplate] >[id=phonerow_" + index + "] [jqxb-itemdatamember=number]").change();
                ok(OnBeforeUpdateCounter == 1, " BeforeUpdate event has already occured ");
                ok(OnAfterUpdateCounter == 1, " AfterUpdate event has already occured ");
                ok(jQXB.getDataSource("MyDataSource")[index].number == newValue, "  Data source object's property  was updated - the case when BeforeUpdate handler returns nothing");
                ok($("[jqxb-templatecontainer=phoneTemplate]> [id=phonerow_" + index + "] [jqxb-itemdatamember=number]").val() == newValue, " Binded textbox was updated too");
                //Clear event handlers for next tests                 
                jQXB.delOnBeforeUpdatehnd(BeforeUpdatehnd);
                jQXB.delOnAfterUpdatehnd(AfterUpdatehnd);
            });

            test("BeforeTemplateBind/ TemplateItemBound  events ", 30, function () {
                var OnBeforeTemplateBindCounter = 0;
                var OnTemplateItemBoundCounter = 0;
                var index = 1; // index of the element which is going to be changed
                var newValue = 555555;
                jQXB.initialize();
                jQXB.setDataSource("MyDataSource", Person1.Address.Phones);
                function OnBeforeTemplateBindhnd(dataSourceName, jsobject, templateName) {
                    switch (dataSourceName) {
                        case 'MyDataSource':
                            if (templateName == "phoneTemplate") {
                                ok(jsobject === Person1.Address.Phones, "Person1 phones are going to be bound with phoneTemplate");
                                ok(templateName == "phoneTemplate", "phoneTemplate is one of the  templates now bound with MyDataSource");
                            }
                            if (templateName == "copyPhoneTemplate") {
                                ok(jsobject === Person1.Address.Phones, "Person1 phones are going to be bound with copyPhoneTemplate");
                                ok(templateName == "copyPhoneTemplate", "copyPhoneTemplate is one of the  templates now bound with MyDataSource");
                            }
                            OnBeforeTemplateBindCounter++;
                            break;
                    }
                }
                jQXB.addOnBeforeTemplateBindhnd(OnBeforeTemplateBindhnd);
                function OnTemplateItemBoundhnd(dataSourceName, templateName, occurrency, itemData, itemTemplate) {
                    switch (dataSourceName) {
                        case 'MyDataSource':
                            if (templateName == "phoneTemplate") {
                                ok(templateName == "phoneTemplate", "phoneTemplate is one of the  templates now bound with MyDataSource");
                                ok(occurrency == OnTemplateItemBoundCounter, '');
                                ok(itemData == Person1.Address.Phones[occurrency], "Person1 phone with index==" + occurrency + " was bound with with particular template item");
                                ok(itemTemplate.html() == $("[jqxb-templatecontainer=phoneTemplate]> [id=phonerow_" + occurrency + "]").html(), "itemTemplate contains HTML of the currently associated template item");

                            }
                            if (templateName == "copyPhoneTemplate") {
                                ok(templateName == "copyPhoneTemplate", "copyPhoneTemplate is one of the  templates now bound with MyDataSource");
                                ok(occurrency == OnTemplateItemBoundCounter - 3, '');
                                ok(itemData == Person1.Address.Phones[occurrency], "Person1 phone with index==" + occurrency + " was bound with with particular template item");
                                ok(itemTemplate.html() == $("[jqxb-templatecontainer=phoneTemplate]> [id=phonerow_" + occurrency + "]").html(), "itemTemplate contains HTML of the currently associated template item");
                            }
                            OnTemplateItemBoundCounter++;
                            break;
                    }
                }
                jQXB.addOnTemplateItemBoundhnd(OnTemplateItemBoundhnd);
                jQXB.doBind("MyDataSource");
                ok(OnBeforeTemplateBindCounter == 2, "BeforeTemplateBind event occured 2 times - 1 time for each template on the page bound with MyDataSource");
                ok(OnTemplateItemBoundCounter == 6, "TemplateItemBound event occured 6 times - 1 time for each template item on the page bound with MyDataSource");
                //Clear event handlers for next tests                 
                jQXB.delOnBeforeTemplateBindhnd(OnBeforeTemplateBindhnd);
                jQXB.delOnTemplateItemBoundhnd(OnTemplateItemBoundhnd);
            });

            module("Controls refreshing");
            test("Refresh controls", 7, function () {
                jQXB.initialize();
                //set data source without possibility to autorefesh
                jQXB.setDataSource("MyDataSource", Person3, false).doBind("MyDataSource");
                ok($("#inputElement").val() == 'Andrew' &&
                jQuery('#spanElement').html() == 'Andrew' &&
                jQuery('#hrefElement').attr('href') == 'Andrew' &&
                jQuery('#divElement').text() == 'Andrew', "Initial set up  ");
                // change  #inputElement value and look what  will happen with another bound elements after change event fire
                $("#inputElement").val("Kevin");
                $("#inputElement").change();
                // refresh will not happen
                ok(jQuery('#spanElement').html() == 'Andrew', "Control was not refreshed");
                ok(jQuery('#hrefElement').attr('href') == 'Andrew', "Control was not refreshed");
                ok(jQuery('#divElement').text() == 'Andrew', "Control was not refreshed");

                //explicitly refresh controls
                jQXB.refreshControls("MyDataSource");

                // controls were refreshed:
                ok(jQuery('#spanElement').html() == 'Kevin', "Control was  refreshed");
                ok(jQuery('#hrefElement').attr('href') == 'Kevin', "Control  was refreshed");
                ok(jQuery('#divElement').text() == 'Kevin', "Control  was refreshed");

                // Return Person3.Name to initial value for next tests:
                Person3.Name = "Andrew";

            });


            test("Refresh only particular data member", 4, function () {
                jQXB.initialize();
                //set data source without possibility to autorefesh
                jQXB.setDataSource("MyDataSource", Person2, false).doBind("MyDataSource");
                ok($("#inputElement").val() == 'John' &&
                 jQuery('#spanElement').html() == 'John' &&
                jQuery('#hrefElement').attr('href') == 'John' &&
                jQuery('#divElement').text() == 'John' &&
                jQuery('#buttonElement').val() == 'Blake' &&
                jQuery('#textElement').val() == 'Blake', "Initial set up  ");
                // change  #inputElement value and look what  will happen with another bound elements after change event fire
                // change  #itextElement value and look what  will happen with another bound elements after change event fire
                $("#inputElement").val("Kevin");
                $("#inputElement").change();
                $("#textElement").val("Brown");
                $("#textElement").change();
                // refresh will not happen automatically
                ok(jQuery('#spanElement').html() == 'John' &&
                 jQuery('#hrefElement').attr('href') == 'John' &&
                 jQuery('#divElement').text() == 'John' &&
                 jQuery('#buttonElement').val() == 'Blake', "Controls were not refreshed");

                //explicitly refresh controls bound with Surname(2nd parameter occurency is undefined for non templates)
                jQXB.refreshControls("MyDataSource", undefined, "Surname");

                // Controls related to Name were not refreshed
                ok(jQuery('#spanElement').html() == 'John' &&
                jQuery('#hrefElement').attr('href') == 'John' &&
                jQuery('#divElement').text() == 'John', "Controls related to Name were not refreshed");

                // Control related to Surname was  refreshed
                ok(jQuery('#buttonElement').val() == 'Brown', "Control related to Surname was  refreshed");

                // Return Person2.Surname back to initial value for next tests:
                Person2.Surname = 'Blake';

            });


            test("Refresh template item", 5, function () {

                jQXB.initialize();
                jQXB.setDataSource("MyDataSource", Person3.Address.Phones, false).doBind("MyDataSource");
                ok($("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemdatasourceidx=0] [jqxb-itemdatamember=prefix]").val() == "0342"
                    && $("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemdatasourceidx=0] [jqxb-itemdatamember=number]").val() == 1234567
                    && $("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemdatasourceidx=1] [jqxb-itemdatamember=prefix]").val() == "0456"
                    && $("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemdatasourceidx=1] [jqxb-itemdatamember=number]").val() == 21341234
                   && $("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemdatasourceidx=2] [jqxb-itemdatamember=prefix]").val() == "050"
                    && $("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemdatasourceidx=2] [jqxb-itemdatamember=number]").val() == 37802345
                 , "Initial set up of original phoneTemplate ");

                ok($("[jqxb-templatecontainer=copyPhoneTemplate] [jqxb-itemdatasourceidx=0] [jqxb-itemdatamember=prefix]").val() == "0342"
                    && $("[jqxb-templatecontainer=copyPhoneTemplate] [jqxb-itemdatasourceidx=0] [jqxb-itemdatamember=number]").val() == 1234567
                    && $("[jqxb-templatecontainer=copyPhoneTemplate] [jqxb-itemdatasourceidx=1] [jqxb-itemdatamember=prefix]").val() == "0456"
                    && $("[jqxb-templatecontainer=copyPhoneTemplate] [jqxb-itemdatasourceidx=1] [jqxb-itemdatamember=number]").val() == 21341234
                   && $("[jqxb-templatecontainer=copyPhoneTemplate] [jqxb-itemdatasourceidx=2] [jqxb-itemdatamember=prefix]").val() == "050"
                    && $("[jqxb-templatecontainer=copyPhoneTemplate] [jqxb-itemdatasourceidx=2] [jqxb-itemdatamember=number]").val() == 37802345
                 , "Initial set up of copiyng copyPhoneTemplate ");


                // change prefix and number of the 1st and 2nd template  items  of the original phoneTemplate and fire change event:
                $("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemdatasourceidx=0] [jqxb-itemdatamember=prefix]").val("3344").change();
                $("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemdatasourceidx=0] [jqxb-itemdatamember=number]").val(77770000).change();
                $("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemdatasourceidx=1] [jqxb-itemdatamember=prefix]").val("1122").change();
                $("[jqxb-templatecontainer=phoneTemplate] [jqxb-itemdatasourceidx=1] [jqxb-itemdatamember=number]").val(555444).change();

                //refresh only second template item (index=1) in the CopyPhoneTemplate and only its prefix:
                jQXB.refreshControls("MyDataSource", 1, "prefix");

                //check that second template item (index=1) in the CopyPhoneTemplate  - prefix datamemeber was refreshed  
                ok($("[jqxb-templatecontainer=copyPhoneTemplate] [jqxb-itemdatasourceidx=1] [jqxb-itemdatamember=prefix]").val() == "1122", "");
                //check that second template item (index=1) in the CopyPhoneTemplate  - number datamemeber was NOT refreshed, it has old value  21341234
                ok($("[jqxb-templatecontainer=copyPhoneTemplate] [jqxb-itemdatasourceidx=1] [jqxb-itemdatamember=number]").val() == 21341234, "");
                //check that 1st template item (index=0) in the CopyPhoneTemplate   was refreshed NOT refreshed at all as expected - it has old values  "0342" and 1234567
                ok($("[jqxb-templatecontainer=copyPhoneTemplate] [jqxb-itemdatasourceidx=0] [jqxb-itemdatamember=prefix]").val() == "0342"
                    && $("[jqxb-templatecontainer=copyPhoneTemplate] [jqxb-itemdatasourceidx=0] [jqxb-itemdatamember=number]").val() == 1234567, "");
            });


            module("jQXB-M");

            test("Subscribe handler to topic", 1, function () {

                jQXB.initialize();
                var handler1 = function (argument, sender) { };
                jQXBM.subscribeMessage("TOPIC1", handler1);
                ok(jQXBM.messageSubscribers["TOPIC1"] != undefined
            && jQXBM.messageSubscribers["TOPIC1"].length == 1
            && jQXBM.messageSubscribers["TOPIC1"][0].toString() == handler1.toString(), "Handler was correctly added to the topic");
                //Unsubscribe handler1 to start next tests from empty point 
                jQXBM.unsubscribeMessage("TOPIC1", handler1);

            });

            test("Unsubscribe a handler from the topic", 2, function () {

                jQXB.initialize();
                var handler1 = function (argument, sender) { var x = 0; };
                jQXBM.subscribeMessage("TOPIC1", handler1);
                ok(jQXBM.messageSubscribers["TOPIC1"].length == 1, "Handler was added to the topic");
                jQXBM.unsubscribeMessage("TOPIC1", handler1);
                ok(jQXBM.messageSubscribers["TOPIC1"].length == 0, "Handler was unsubscribed from the topic");

            });

            test("Should NOT be able to add the same handler twice", 2, function () {
                jQXB.initialize();
                var handler1 = function (argument, sender) { var x = 0; };
                jQXBM.subscribeMessage("TOPIC1", handler1);
                ok(jQXBM.messageSubscribers["TOPIC1"].length == 1, "Handler was added to the topic");
                jQXBM.subscribeMessage("TOPIC1", handler1);
                ok(jQXBM.messageSubscribers["TOPIC1"].length == 1, "The same handler was NOT  added to the topic");
                //Unsubscribe handler1 to start next tests from empty point 
                jQXBM.unsubscribeMessage("TOPIC1", handler1);

            });

            test("Subscribe handlers to ALL topics", 2, function () {

                jQXB.initialize();
                var handler1 = function (argument, sender) { };
                var handler2 = function (argument, sender) { return argument; };
                jQXBM.subscribeMessage("", handler1);
                ok(jQXBM.messageSubscribers['any'].length == 1
            && jQXBM.messageSubscribers['any'][0].toString() == handler1.toString(), "Handler was added to all topics");
                jQXBM.subscribeMessage(null, handler2);
                ok(jQXBM.messageSubscribers['any'].length == 2
            && jQXBM.messageSubscribers['any'][1].toString() == handler2.toString(), "2nd handler was added to all topics");

                //Unsubscribe handler1 and handler2 to start next tests from empty point 
                jQXBM.unsubscribeMessage("", handler1);
                jQXBM.unsubscribeMessage("", handler2);

            });

            test("Unsubscribe generic handlers from 'any' topic", 2, function () {

                jQXB.initialize();
                var handler1 = function (argument, sender) { };
                var handler2 = function (argument, sender) { return argument; };
                //Subscribe 2 generic handlers; 
                jQXBM.subscribeMessage("", handler1);
                jQXBM.subscribeMessage(null, handler2);
                ok(jQXBM.messageSubscribers['any'].length == 2, "Handlers were added to 'any' topic");
                //Unsubscribe handler1 and handler2 
                jQXBM.unsubscribeMessage("", handler1);
                jQXBM.unsubscribeMessage("", handler2);
                ok(jQXBM.messageSubscribers['any'].length == 0, "Handlers were removed from 'any' topic");

            });



            test("simple messaging test", 2, function () {

                jQXB.initialize();
                function handler1(argument, sender) {
                    jQXB.setDataSource("MessageSource1", argument).doBind("MessageSource1");

                }
                jQXBM.subscribeMessage("TOPIC1", handler1);
                ok($("#message1").val() == "", "#message1 input element is empty");
                jQXBM.fireMessage("TOPIC1", Person1);
                // handler was invoked and set up correct value of bound control 
                ok($("#message1").val() == "Anthony", "#message1 input element is filled with value after handler1 was executed");
                //Unsubscribe handler1 to start next tests from empty point 
                jQXBM.unsubscribeMessage("TOPIC1", handler1);

            });

            test("Fire message to 1 named topic with a few handlers subscribed", 2, function () {

                jQXB.initialize();
                function handler1(argument, sender) { jQXB.setDataSource("MessageSource1", argument).doBind("MessageSource1"); }
                function handler2(argument, sender) { jQXB.setDataSource("MessageSource2", argument).doBind("MessageSource2"); }
                jQXBM.subscribeMessage("TOPIC1", handler1);
                jQXBM.subscribeMessage("TOPIC1", handler2);
                jQXBM.fireMessage("TOPIC1", Person1);
                //check if handler1  from TOPIC1 set up correct value of bound control
                ok($("#message1").val() == "Anthony", "OK");
                //check if handler2  from TOPIC1 set up correct value of bound control
                ok($("#message2").val() == "Murray", "OK");

                //Unsubscribe handlers to start next tests from empty point 
                jQXBM.unsubscribeMessage("TOPIC1", handler1);
                jQXBM.unsubscribeMessage("TOPIC1", handler2);

            });

            test("Fire messages to different topics ", 2, function () {

                jQXB.initialize();
                function handler1(argument, sender) {
                    jQXB.setDataSource("MessageSource1", argument).doBind("MessageSource1");

                }
                function handler2(argument, sender) {
                    jQXB.setDataSource("MessageSource2", argument).doBind("MessageSource2");

                }
                $("#clickButton").bind('click', function () { jQXBM.fireMessage("TOPIC1", Person1); });
                $("#clickButton").bind('click', function () { jQXBM.fireMessage("TOPIC2", Person2); });
                jQXBM.subscribeMessage("TOPIC1", handler1);
                jQXBM.subscribeMessage("TOPIC2", handler2);
                $("#clickButton").click();
                //check if handler1  from TOPIC1 set up correct value of bound control
                ok($("#message1").val() == "Anthony", "Person1.Name should be here");
                //check if handler2  from TOPIC2 set up correct value of bound control
                ok($("#message2").val() == "Blake", "Person2.Surname should be here");

                //Unsubscribe handlers to start next tests from empty point 
                jQXBM.unsubscribeMessage("TOPIC1", handler1);
                jQXBM.unsubscribeMessage("TOPIC2", handler2);
                $("*").unbind();

            });

            test("Handlers subscribed to unnamed topic receive messages sent to unnamed topic ", 2, function () {

                jQXB.initialize();
                function handler1(argument, sender) {
                    jQXB.setDataSource("MessageSource1", argument).doBind("MessageSource1");

                }
                function handler2(argument, sender) {
                    jQXB.setDataSource("MessageSource2", argument).doBind("MessageSource2");

                }

                $("#clickButton").bind('click', function () { jQXBM.fireMessage("", Person3); });
                //subscribe handlers to unnamed topic
                jQXBM.subscribeMessage("", handler1);
                jQXBM.subscribeMessage("", handler2);
                //fire event 
                $("#clickButton").click();
                //check if handler1  from 'any'  topic set up correct value of bound control
                ok($("#message1").val() == Person3.Name, "handler1  from 'any'  topic set up correct value of bound control");
                //check if handler2  from 'any'  topic set up correct value of bound control
                ok($("#message2").val() == Person3.Surname, "handler2  from 'any'  topic set up correct value of bound control");

                //Unsubscribe handlers to start next tests from empty point 
                jQXBM.unsubscribeMessage("", handler1);
                jQXBM.unsubscribeMessage("", handler2);
                $("*").unbind();
                //clear bound input fields for next tests
                $("#message1").val("");
                $("#message2").val("");
            });

            test("Fire message to named topic - generic 'any' handler receives it TOO ", 3, function () {

                jQXB.initialize();
                function handler1(argument, sender) {
                    jQXB.setDataSource("MessageSource1", argument).doBind("MessageSource1");

                }
                function handler2(argument, sender) {
                    jQXB.setDataSource("MessageSource2", argument).doBind("MessageSource2");

                }
                jQXBM.subscribeMessage("TOPIC1", handler1);
                jQXBM.subscribeMessage("", handler2);
                ok($("#message1").val() != Person3.Name && $("#message2").val() != Person4.Surname, "Check input boxes before change");
                // fire message
                jQXBM.fireMessage("TOPIC1", Person4);
                //check if  handler1 receives the message from TOPIC1  
                ok($("#message1").val() == Person4.Name, "OK");
                //check if generic 'any' handler2 receives the message from TOPIC1  
                ok($("#message2").val() == Person4.Surname, "  Topic1 fired a message, generic 'any' handler2 received the message and set up #message2 value to Person3.Name ");
                //Unsubscribe handlers to start next tests from empty point 
                jQXBM.unsubscribeMessage("TOPIC1", handler1);
                jQXBM.unsubscribeMessage("", handler2);

            });



            test("Handler receives correct sender", 2, function () {

                jQXB.initialize();
                function handler1(argument, sender) {
                    jQXB.setDataSource("MessageSource1", argument).doBind("MessageSource1");
                    ok(sender.attr("id") == "clickButton", "Correct sender was send to the handler");

                }
                function handler2(argument, sender) {

                    jQXB.setDataSource("MessageSource2", argument).doBind("MessageSource2");
                    ok(sender.attr("id") == "pushButton", "Correct sender was send to the handler");
                }
                $("#clickButton").bind('click', function () {
                    jQXBM.fireMessage("TOPIC1", Person1, $(this));
                });
                $("#pushButton").bind('click', function () { jQXBM.fireMessage("TOPIC2", Person2, $(this)); });

                jQXBM.subscribeMessage("TOPIC1", handler1);
                jQXBM.subscribeMessage("TOPIC2", handler2);
                $("#clickButton").click();
                $("#pushButton").click();
                $("#message1").val("");

            });


        });

    </script>
</head>
<body>
    <h1 id="qunit-header">jQXB Unit Test</h1>
    <h2 id="qunit-banner"></h2>
    <div id="qunit-testrunner-toolbar"></div>
    <h2 id="qunit-userAgent"></h2>
    <ol id="qunit-tests"></ol>
    <div id="qunit-fixture">test markup, will be hidden</div>

    <hr />

    <!-- Binding area -->
    <fieldset>
        <legend>
            <h3>Binding operations</h3>
        </legend>
        <input id="inputElement" type="text" jqxb-datasource="MyDataSource" jqxb-datamember="Name" />
        <br />
        <input id="textElement" type="text" jqxb-datasource="MyDataSource" jqxb-datamember="Surname" />
        <br />
        <input id="buttonElement" type="button" jqxb-datasource="MyDataSource" jqxb-datamember="Surname" />
        <br />
        <span id="spanElement" jqxb-datasource="MyDataSource" jqxb-datamember="Name" jqxb-bindedattribute="html"></span>
        <br />
        <div id="divElement" jqxb-datasource="MyDataSource" jqxb-datamember="Name" jqxb-bindedattribute="text"></div>
        <br />
        <a id="hrefElement" jqxb-datasource="MyDataSource" jqxb-datamember="Name" jqxb-bindedattribute="href">Test Link</a>
        <br />
        <input id="checkBoxElement" type="checkbox" jqxb-datasource="MyDataSource" jqxb-datamember="Name" />
        <br />
        <select id="listBox" jqxb-listsource="ListSource" jqxb-listvalue="prefix" jqxb-listtext="number"></select>
        <br />
        <select id="listBoxDataPath" jqxb-listsource="MyDataSourcePath" jqxb-listvalue="prefix" jqxb-listtext="number" jqxb-listdatapath="Address.Phones"></select>


    </fieldset>

    <!--Templates area -->
    <fieldset>
        <legend>
            <h3>Template operations</h3>
        </legend>
        <table>
            <caption>
                <h3>Test phones table: </h3>
            </caption>
            <thead>
                <tr>
                    <th>Prefix</th>
                    <th>Number</th>
                </tr>
            </thead>
            <tbody jqxb-templatecontainer="phoneTemplate" jqxb-datasource="MyDataSource">
                <tr jqxb-template="phoneTemplate" jqxb-templateitemidprfx="phonerow" style="display: none;">
                    <td>
                        <input type="text" jqxb-itemdatamember="prefix" /></td>
                    <td>
                        <input type="text" jqxb-itemdatamember="number" /></td>
                </tr>
            </tbody>
        </table>


       <table>
            <caption>
                <h3>Test phones table: </h3>
            </caption>
            <thead>
                <tr>
                    <th>Prefix</th>
                    <th>Number</th>
                </tr>
            </thead>
            <tbody jqxb-templatecontainer="phoneTemplateDataPath" jqxb-datasource="MyDataSourcePath" jqxb-datapath="Address.Phones">
                <tr jqxb-template="phoneTemplateDataPath" jqxb-templateitemidprfx="phonerow" style="display: none;">
                    <td>
                        <input type="text" jqxb-itemdatamember="prefix" /></td>
                    <td>
                        <input type="text" jqxb-itemdatamember="number" /></td>
                </tr>
            </tbody>
        </table>

        <table>
            <caption>
                <h3>Copy of the test phones table:</h3>
            </caption>
            <thead>
                <tr>
                    <th>Prefix</th>
                    <th>Number</th>
                </tr>
            </thead>
            <tbody jqxb-templatecontainer="copyPhoneTemplate" jqxb-datasource="MyDataSource">
                <tr jqxb-template="copyPhoneTemplate" jqxb-templateitemidprfx="copyPhoneRow" style="display: none;">
                    <td>
                        <input type="text" jqxb-itemdatamember="prefix" /></td>
                    <td>
                        <input type="text" jqxb-itemdatamember="number" /></td>
                </tr>
            </tbody>
        </table>

    </fieldset>


    <!--Messaging area -->
    <fieldset>
        <legend>
            <h3>Message operations</h3>
        </legend>

        <input id="message1" type="text" jqxb-datasource="MessageSource1" jqxb-datamember="Name" />
        <input id="message2" type="text" jqxb-datasource="MessageSource2" jqxb-datamember="Surname" />
        <input type="button" id="clickButton" value="ClickMe" />
        <input type="button" id="pushButton" value="ClickMe" />

    </fieldset>
</body>
</html>
